from graphics import *
from math import *

win = GraphWin("Project Awesome",800,630)
portals=[]

def main():

    menuBox = Rectangle(Point(0,0),Point(800,30))
    menuBox.draw(win)

    #walls around Game Field#
    wallMaker(0,33,800,33)
    wallMaker(3,30,3,630)
    wallMaker(0,627,800,627)
    wallMaker(797,30,797,630)

    ########################### LEVEL ONE ##############################

    #walls for level one#
    wallMaker(230,330,230,30)
    wallMaker(560,630,560,30)
    #portals for level two#
    portals=[]
    portalMaker(260,33,320,33,620,627,680,627)
    portals.append([260,33,320,33,620,627,680,627])
    portals.append([620,627,680,627,260,33,320,33])

    #start of particle for level one#
    particle = Circle(Point(100,500),10)
    particle.setFill('black')
    particle.draw(win)
    #start of goal for level one#
    goal = Circle(Point(600,500),10)
    goal.setFill('yellow')
    goal.draw(win)

    #MENU#
    newChargeButton = Rectangle(Point(0,30),Point(200,0))
    newChargeButton.setFill('yellow')
    newChargeButtonlabel=Text(Point(100,15),"Type of Charge:")
    newChargeButton.draw(win)
    newChargeButtonlabel.draw(win)

    positiveChargeButton = Rectangle(Point(200,30),Point(230,0))
    positiveChargeButton.setFill('blue')
    negativeChargeButton = Rectangle(Point(230,30),Point(260,0))
    negativeChargeButton.setFill('red')
    negativeChargeButton.draw(win)
    positiveChargeButton.draw(win)
    posNeg(215,15,1)
    posNeg(245,15,-1)

    placeChargeButton = Rectangle(Point(290,30),Point(420,0))
    placeChargeButton.setFill('Purple')
    placeChargeButtonlabel=Text(Point(355,15),"Place Charge")
    placeChargeButton.draw(win)
    placeChargeButtonlabel.draw(win)

    startButton= Rectangle(Point(420,30),Point(800,0))
    startButton.setFill('green')
    startButtonlabel=Text(Point(610,15),"Start")
    startButton.draw(win)
    startButtonlabel.draw(win)


    ###################### SETTING CHARGES ##################
    chargeList=[]
    start =False
    charge = 1
    ptcharge = Circle(Point(-2,-2),5)
    ptcharge.draw(win)
    done = False
    place = False
    while (not done):
        place=False
        while (not place):
            mouse = win.getMouse()
            x = mouse.getX()
            y = mouse.getY()
            if y>30:
                ptcharge.undraw()
                x1=x
                y1=y
                ptcharge = Circle(Point(x1,y1),10)
                if charge == -1:
                    ptcharge.setFill('red')
                else:
                    ptcharge.setFill('blue')
                ptcharge.draw(win)
            elif y<=30 and (200<=x<=230):
                charge = 1
            elif y<=30 and (230<=x<=260):
                charge=-1
            elif (y<=30) and (290<=x) and (charge != 0):
                chargeList.append([x1,y1,charge])
                RedOrBlue([x1,y1,charge])
                posNeg(x1,y1,charge)
                place=True
                if x>420:
                    done=True



########### ONCE CHARGES ARE SET and START is hit. MOVEMENT   #################
    t = 0.05
    vx = 0
    vy = 0
    there=False
    while (not there):
        fx,fy= multiforce(particle.getCenter().getX(),particle.getCenter().getY(),chargeList)
        vx = vx + fx*t
        vy = vy + fy*t
        particle.move(vx*t,vy*t)
        goalDistance= sqrt((particle.getCenter().getX()-goal.getCenter().getX())**2 + (particle.getCenter().getY()-goal.getCenter().getY())**2)
        #### WINNING AND LOSING ######
        # UNIVERSAL WINNinG/LOSING#
    
        if goalDistance<10:
            message = Text(Point(400,315),"LEVEL COMPLETE");
            message.draw(win)
            time.sleep(2.5)
            there = True

        for ports in portals:
            if portalCheck(particle.getCenter().getX(), particle.getCenter().getY(), ports):
                particle.undraw()
                particle = Circle(Point(ports[6]-(ports[2]-particle.getCenter().getX()),ports[5]+13),10)
                particle.setFill('black')
                particle.draw(win)

        if particle.getCenter().getX()<16 or particle.getCenter().getX()> 784 or particle.getCenter().getY()<36 or particle.getCenter().getY()> 614:
                message = Text(Point(400,315),"LEVEL FAILED");
                message.draw(win)
                time.sleep(2.5)
                there = True
        # SPECIFIC TO LEVEL ONE WINNING?LOSING #
        elif (abs(particle.getCenter().getX()-230)<10 and particle.getCenter().getY() <330) or (abs(particle.getCenter().getX()-560)<10 and particle.getCenter().getY()>310):
            message = Text(Point(400,315),"LEVEL FAILED");
            message.draw(win)
            time.sleep(2.5)
            there = True
        time.sleep(t)


def force(x1,y1,x2,y2,charge):
    distance = sqrt((x1-x2)**2+(y1-y2)**2)
    a = x1-x2
    b= y1-y2
    if distance==0:
        forceMagnitude=0
    elif a==0 and b!=0:
        fx = 0
        directionX=0
        fy = abs((8.987*(10**5))*(charge/(distance**2)))
        directionY= b/abs(b)
    elif a!=0 and b==0:
        fy = 0
        directionX= a/abs(a)
        fx = abs((8.987*(10**5))*(charge/(distance**2)))
        directionY=0
    else:
        theta1 = acos(a/distance)
        theta2 = asin(b/distance)
        forceMagnitude = (8.987*(10**5))*(charge/(distance**2))
        fx = abs(forceMagnitude*cos(theta1))
        fy = abs(forceMagnitude*sin(theta2))
        directionX=a/abs(a)
        directionY=b/abs(b)
    if charge == -1:
        directionX, directionY= -directionX,-directionY
    return fx,directionX,fy,directionY


def multiforce(x,y,list):
    totalfx = 0
    totalfy = 0
    for sublist in list:
        fx, dx, fy, dy =  force(x, y, sublist[0], sublist[1], sublist[2])
        totalfx += fx*dx
        totalfy += fy*dy
    return totalfx, totalfy


def RedOrBlue(list):
        chosenCharge=Circle(Point(list[0],list[1]),10)
        if list[2]==1:
           chosenCharge.setFill('blue')
        elif list[2]==-1:
            chosenCharge.setFill('red')
        return chosenCharge.draw(win)

def posNeg(x,y,num):
    circ=Circle(Point(x,y),8)
    circ.setOutline('white')
    lin1=Line(Point(x+6,y),Point(x-6,y))
    lin1.setOutline('white')
    lin2=Line(Point(x,y-6),Point(x,y+6))
    lin2.setOutline('white')
    if num==1:
        return circ.draw(win), lin1.draw(win), lin2.draw(win)
    else:
        return lin1.draw(win), circ.draw(win)

def wallMaker(x1,y1,x2,y2):
    if x1==x2:
        wall = Rectangle(Point(x1+3,y1),Point(x2-3,y2))
    elif y1==y2:
        wall = Rectangle(Point(x1,y1+3),Point(x2,y2-3))
    wall.setFill('dark gray')
    return wall.draw(win)

def portalMaker(x1,y1,x2,y2,x3,y3,x4,y4):
    if x1==x2 and x3==x4:
        portal1 = Rectangle(Point(x1+3,y1),Point(x2-3,y2))
        portal2 = Rectangle(Point(x3+3,y3),Point(x4-3,y4))
        orientation = 1
    elif y1==y2 and y3==y4:
        portal1 = Rectangle(Point(x1,y1+3),Point(x2,y2-3))
        portal2 = Rectangle(Point(x3,y3+3),Point(x4,y4-3))
        orientation = 1
    elif x1==x2 and y3 ==y4:
        portal1 = Rectangle(Point(x1+3,y1),Point(x2-3,y2))
        portal2 = Rectangle(Point(x3,y3+3),Point(x4,y4-3))
        orientation = -1
    elif y1==y2 and x3 == x4:
        portal1 = Rectangle(Point(x1,y1+3),Point(x2,y2-3))
        portal2 = Rectangle(Point(x3+3,y3),Point(x4-3,y4))
        orientation = -1
    portal1.setFill('orange')
    portal2.setFill('orange')
    return portal1.draw(win), portal2.draw(win)
    return portals.append([x1,y1,x2,y2,x3,y3,x4,y4])

def portalCheck(x,y,ports):
    if (ports[0]+10  < x < ports[2]-10 and y < ports[1]+20):
        inPortal=True
    else: inPortal = False
    return inPortal

def menu():
    #MENU APPEARANCE#
    menuOption = 0
    menu = GraphWin("Project Awesome",800,630)
    singlePlayerOption = Rectangle(Point(300,100),Point(500,200))
    singlePlayerOption.setFill('yellow')
    singlePlayerOption.draw(menu)
    singlePlayerOptionLabel = Text(Point(400,150),"CAMPAIGN")


    levelCreatorOption = Rectangle(Point(300,250),Point(500, 350))
    levelCreatorOption.setFill('yellow')
    levelCreatorOption.draw(menu)
    levelCreatorOptionLabel = Text(Point(400,300),"CREATE YOUR OWN LEVEL")
    levelCreatorOptionLabel.draw(menu)

    quitOption = Rectangle(Point(300,400), Point(500, 500))
    quitOption.setFill('yellow')
    quitOption.draw(menu)
    quitOptionLabel = Text(Point(400,450), "QUIT")

    #GETTING FIRST CLICK#
    mouse = menu.getMouse()
    x = mouse.getX()
    y = mouse.getY()
    if (300<= x <= 500 and 100 <= y <= 200):

        levelOneOption = Rectangle(Point(300,100),Point(500,200))
        singlePlayerOptionLabel.undraw()
        levelOneOptionLabel = Text(Point(400,150),"LEVEL 1")
        levelOneOptionLabel.draw(menu)
        
        levelTwoOption = Rectangle(Point(300,250),Point(500, 350))
        levelCreatorOptionLabel.undraw()
        levelTwoOptionLabel = Text(Point(400,300),"LEVEL 2")
        levelTwoOptionLabel.draw(menu)
        
        levelThreeOption = Rectangle(Point(300,400), Point(500, 500))
        quitOptionLabel.undraw()
        levelThreeOptionLabel = Text(Point(400,450),"LEVEL 3")
        levelTwoOptionLabel.draw(menu)


        mouse = win.getMouse()
        x = mouse.getX()
        y = mouse.getY()
        if (300 <= x <= 500 and 100 <= y <= 200):
            menuOption = 11
        elif (300<= x <= 500 and 250 <= y <= 350):
            menuOption = 12
        elif (300<= x <= 500 and 400 <= y <= 500):
            level=13
    elif (300<= x <= 500 and 250 <= y <= 350):
        menuOption = 2
    elif (300<= x <= 500 and 400 <= y <= 500):
        menuOption = 3
    return menuOption

main()

    